Java基础知识(七)
引用传递分析实例
引用传递
1.引用传递核心意义:同一块堆内存可以被不同栈内存所指向,不同栈内存可以对同一块堆内存进行修改。
范例:引用传递
public class Message {
private int num = 10;
public Message(int num) {
this.num = num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
public class TMessage {
public static void main(String[] args) {
Message msg = new Message(30);
System.out.println(msg.getNum()); // 30
fun(msg); // 引用传递
System.out.println(msg.getNum()); // 100
}
public static void fun(Message temp) {
temp.setNum(100);
}
}
对上述代码进行内存分析:
2.引用
public class Demo {
public static void main(String[] args) {
String msg = "Hello";
fun(msg);
System.out.println(msg); // Hello
}
public static void fun(String temp) {
temp = "World";
}
}
出现上述结果原因:String对象的内容一旦声明不可改变,对象内容的改变依靠的是引用地址的改变。内存分析如下:
3.引用传递
public class Message {
private String info = "nihao";
public Message(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
public class TMessage {
public static void main(String[] args) {
Message msg = new Message("Hello");
System.out.println(msg.getInfo()); // Hello
fun(msg);
System.out.println(msg.getInfo()); // World
}
public static void fun(Message temp) {
temp.setInfo("World");
}
}
内存分析如下:
上述内存分析,是按照int型数据的特点进行的。实际info是String对象,应该按照如下方式进行分析:
结论:虽然String
是一个类,属于引用数据类型,但由于其内容不可改的特点,我们常将其当作基本数据类型。即每个String变量只能保存一个数据。
引用传递实例
要求:通过面向对象的方式描述每个人有车或没车。
实现步骤:
1.创建数据库:应设计两张表:汽车表
和人员表
;
2.根据数据表,定义两个类:
(编写简单java类时,可按照数据表的设计来写,规则如下:
类名 = 表名;
属性名(类型) = 表字段(类型);
一个实例化对象 = 一行记录;
多个实例化对象 = 多行记录
引用关系 = 外键描述)
public class Member {
private int mId;
private String name;
}
public class Car {
private String pName;
}
3.利用引用
来描述两个类的外键,从而使得两个类有联系
public class Member {
private int mId;
private String name;
// 有Car类实例化对象表示有车
// Car为null表示没车
private Car car;
public Member(int mId, String name) {
this.mId = mId;
this.name = name;
}
public String getInfo() {
return "人员编号:" + this.mId + ",姓名:" + this.name;
}
}
public class Car {
private Member member; // 车属于一个人
private String pName;
public Car(String pName) {
this.pName = pName;
}
public String getInfo() {
return "车名:" + this.pName;
}
}
4.当两个类的对象产生,为这两个对象设置彼此的关系:
public class Member {
private int mId;
private String name;
// 有Car类实例化对象表示有车
// Car为null表示没车
private Car car;
public Member(int mId, String name) {
this.mId = mId;
this.name = name;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String getInfo() {
return "人员编号:" + this.mId + ",姓名:" + this.name;
}
}
public class Car {
private Member member; // 车属于一个人
private String pName;
public Car(String pName) {
this.pName = pName;
}
public String getInfo() {
return "车名:" + this.pName;
}
public Member getMember() {
return member;
}
public void setMember(Member member) {
this.member = member;
}
}
5.测试
测试分为两步:
(1)根据定义的结构关系设置数据
(2)根据定义的结构关系取出数据
public class TCar {
public static void main(String[] args) {
// 1. 设置数据
Member m = new Member(1,"张三");
Car c = new Car("宝马");
// 设置车与人的关系:张三有辆宝马
m.setCar(c);
c.setMember(m);
// 2. 取出数据
// 通过人找到车
System.out.println(m.getCar().getInfo());
// 通过车找到人
System.out.println(c.getMember().getInfo());
}
}
6.进一步设计:每个人都有孩子,孩子还可能有车
思路:
(1)设计一个孩子类,如有孙子,在设计孙子类,以此类推。该方案过于冗余,不合适;
(2)在Member类中设计属性child,类型为Member:
private Member child; // 孩子
public Member getChild() {
return child;
}
public void setChild(Member child) {
this.child = child;
}
测试:
public class TCar {
public static void main(String[] args) {
// 1. 设置数据
Member m = new Member(1,"张三");
Member child = new Member(1,"张四");
Car c = new Car("宝马");
Car cc =new Car("法拉利");
// 设置车与人的关系:张三有辆宝马
m.setCar(c);
c.setMember(m);
// 设置车与人的关系:张四有辆法拉利
child.setCar(cc);
c.setMember(child);
// 设置人与人的关系:张四是张三的儿子
m.setChild(child);
// 2. 取出数据
// 通过人找到车
System.out.println(m.getCar().getInfo());
// 通过车找到人
System.out.println(c.getMember().getInfo());
// 通过人找到孩子
System.out.println(m.getChild().getInfo());
// 通过人找到孩子的车
System.out.println(m.getChild().getCar().getInfo());
}
}
7.利用引用描述电脑:电脑由主机、键盘、内存、CPU、显卡等组成,下面用伪代码描述:
class 键盘{}
class 鼠标{}
class CPU{}
class 硬盘{}
class 内存{}
class 显示器{}
class 主机{}
class 主板{}
class 主机{
private CPU 对象[];
private 硬盘 对象[];
private 主板 对象;
private 内存 对象[];
}
class 电脑{
private 主机 对象;
private 显示器 对象;
private 键盘 对象;
private 鼠标 对象;
}
上述设计思路称为合成设计模式
。引用是实现两个不同类之间互相关联的主要手段。
数据表与简单Java类映射
要求:通过程序描述部门和雇员关系
属性:
·dept:deptno,dname,loc;
·emp:empno, ename,job,sal,comm,deptno,mgr
关系:
·一个部门有多个雇员;
·一个雇员有一个或零个领导。
第一步: 根据数据表创建简单java类
/**
* 部门类
*/
public class Dept {
private int depNo; // 编号
private String dName; // 名字
private String address; // 地址
// setter,getter,无参构造方法略
public Dept(int depNo, String dName, String address) {
this.depNo = depNo;
this.dName = dName;
this.address = address;
}
public String getInfo() {
return "部门编号:" + this.depNo +
",部门名称:" + this.dName +
",地址:" + this.address;
}
}
/**
* 员工类
*/
public class Emp {
private int eNo; // 编号
private String eName; // 姓名
private String job; // 职位
private double sal; // 工资
private double comm; // 佣金
// setter,getter,无参构造方法略
public Emp(int eNo, String eName, String job, double sal, double comm) {
this.eNo = eNo;
this.eName = eName;
this.job = job;
this.sal = sal;
this.comm = comm;
}
public String getInfo() {
return "编 号" + this.eNo + "\n" +
"姓 名" + this.eName + "\n" +
"职 位" + this.job + "\n" +
"工 资" + this.sal + "\n" +
"佣 金" + this.comm;
}
}
第二步:设置外键关系
· 一个雇员属于一个部门,应在雇员类中保存部门信息
private Dept dept; // 对应的部门信息
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
· 一个部门有的多个雇员,可用数组在部门类中保存雇员信息:
private Emp emps[]; // 多个雇员信息
public Emp[] getEmps() {
return emps;
}
public void setEmps(Emp[] emps) {
this.emps = emps;
}
· 一个雇员有一个领导(定义在Emp类中)
private Emp mgr; // 领导信息
public Emp getMgr() {
return mgr;
}
public void setMgr(Emp mgr) {
this.mgr = mgr;
}
第三步:测试
(1)设置数据:
public class Demo {
public static void main(String[] args) {
// 1. 产生对象
Dept dept = new Dept(10, "财务部", "北京"); // 部门信息
// 员工信息
Emp eA = new Emp(1111, "张三", "保安", 800.0, 0.0);
Emp eB = new Emp(1101, "李四", "秘书", 2800.0, 500.0);
Emp eC = new Emp(1001, "王五", "经历", 6800.0, 1500.0);
// 2. 设置员工与领导关系
eA.setMgr(eB);
eB.setMgr(eC);
// 3. 设置员工和部门关系
eA.setDept(dept);
eB.setDept(dept);
eC.setDept(dept);
dept.setEmps(new Emp[]{eA, eB, eC});
}
}
(2):根据给定的结构取出数据,要求如下:
|-根据一个雇员查询他所对应的领导信息和部门信息;
|-根据一个部门查询所有雇员以及其所对应的领导信息;
// 第二步:取出数据
// 1. 通过员工找到领导信息和部门信息
System.out.println(eA.getInfo()); // 获取员工信息
System.out.println("\t|-" + eA.getMgr().getInfo()); // 获取领导信息
System.out.println("\t|-" + eA.getDept().getInfo()); // 获取部门信息
// 2. 根据部门找到所有员工及其领导信息
System.out.println("---------------------------------------------");
System.out.println(dept.getInfo());
for (int x = 0; x < dept.getEmps().length; x++) {
System.out.println("\t|-" + dept.getEmps()[x].getInfo()); // 获取员工信息
if (dept.getEmps()[x].getMgr() != null) {
System.out.println("\t\t|-" + dept.getEmps()[x].getMgr().getInfo()); // 获取领导信息
}
}
上述代码都是依靠代码链取出数据。
一对多映射
要求:通过程序描述省份和城市的关系
1.通过一个城市找到它对应的省份信息;
2.通过一个省份找到所有城市的信息。
class Province {
private int pId;
private String pName;
private City cities[];
// getter,setter,无参构造方法略
public Province(int pId, String pName) {
this.pId = pId;
this.pName = pName;
}
public City[] getCities() {
return cities;
}
public void setCities(City[] cities) {
this.cities = cities;
}
public String getInfo() {
return "省份ID:" + this.pId + ",省名:" + this.pName;
}
}
class City {
private int cId;
private String cName;
private Province province;
// getter,setter,无参构造方法略
public City(int cId, String cName) {
this.cId = cId;
this.cName = cName;
}
public Province getProvince() {
return province;
}
public void setProvince(Province province) {
this.province = province;
}
public String getInfo() {
return "城市ID:" + this.cId + ",市名:" + this.cName;
}
}
public class Demo {
public static void main(String[] args) {
Province province = new Province(350, "福建省");
City cA = new City(1, "福州");
City cB = new City(2, "厦门");
City cC = new City(3, "泉州");
cA.setProvince(province);
cB.setProvince(province);
cC.setProvince(province);
province.setCities(new City[]{cA, cB, cC});
System.out.println(cA.getInfo());
System.out.println("\t|-" + cA.getProvince().getInfo());
System.out.println("==================================");
System.out.println(province.getInfo());
for (int x = 0; x < province.getCities().length; x++) {
System.out.println("\t|-" + province.getCities()[x].getInfo());
}
}
}
上述代码存在不足:每次添加城市,就要修改数组的引用关系
双向一对多映射
要求:通过程序描述类型-子类型-商品的关系
(1)通过一个类型找到它对应的子类型;
(2)过一个类型找到它所对应的商品;
(3)通过一个子类型找到所有对应的商品。
class Type {
private int tId;
private String tName;
private SonType sonTypes[];
private Product products[];
// getter,setter,无参构造方法略
public Type(int tId, String tName) {
this.tId = tId;
this.tName = tName;
}
public SonType[] getSontypes() {
return this.sonTypes;
}
public void setSontypes(SonType[] sontypes) {
this.sonTypes = sontypes;
}
public Product[] getProducts() {
return products;
}
public void setProducts(Product[] products) {
this.products = products;
}
public String getInfo() {
return "类型编号:" + this.tId + ",类型名称:" + this.tName;
}
}
class SonType {
private int sId;
private String sName;
private Type type;
private Product products[];
// getter,setter,无参构造方法略
public SonType(int sId, String sName) {
this.sId = sId;
this.sName = sName;
}
public int getsId() {
return sId;
}
public void setsId(int sId) {
this.sId = sId;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public Product[] getProducts() {
return products;
}
public void setProducts(Product[] products) {
this.products = products;
}
public String getInfo() {
return "子类型编号:" + this.sId + ",子类型名称:" + this.sName;
}
}
class Product {
private int pId;
private String name;
private double price;
private Type type;
private SonType sonType;
// getter,setter,无参构造方法略
public Product(int pId, String name, double price) {
this.pId = pId;
this.name = name;
this.price = price;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public SonType getSonType() {
return sonType;
}
public void setSonType(SonType sonType) {
this.sonType = sonType;
}
public String getInfo() {
return "商品编号:" + this.pId + ",商品名称:" + this.name + ",价格:" + this.price;
}
}
public class Demo {
public static void main(String[] args) {
Type type = new Type(1, "家电类");
SonType stA = new SonType(11, "小型家电");
SonType stB = new SonType(12, "大型家电");
Product pA = new Product(111, "剃须刀", 99.0);
Product pB = new Product(112, "热水壶", 29.0);
Product pC = new Product(121, "电冰箱", 1199.0);
Product pD = new Product(122, "电热水器", 399.0);
stA.setType(type);
stB.setType(type);
pA.setType(type);
pB.setType(type);
pC.setType(type);
pD.setType(type);
type.setSontypes(new SonType[]{stA, stB});
type.setProducts(new Product[]{pA, pB, pC, pD});
pA.setSonType(stA);
pB.setSonType(stA);
pC.setSonType(stB);
pD.setSonType(stB);
stA.setProducts(new Product[]{pA, pB});
stB.setProducts(new Product[]{pC, pD});
System.out.println(type.getInfo());
for (int x = 0; x < type.getSontypes().length; x++) {
System.out.println("\t|- " + type.getSontypes()[x].getInfo());
}
System.out.println("--------------------------------------");
System.out.println(type.getInfo());
for (int x = 0; x < type.getProducts().length; x++) {
System.out.println("\t|- " + type.getProducts()[x].getInfo());
System.out.println("\t\t|- " + type.getProducts()[x].getSonType().getInfo());
}
System.out.println("--------------------------------------");
System.out.println(stA.getInfo());
for (int x = 0; x < stA.getProducts().length; x++) {
System.out.println("\t|- " + stA.getProducts()[x].getInfo());
}
}
}
多对多映射
要求:通过程序描述管理员-角色-组-权限的关系;
(1)根据一个管理员找到它对应的角色,以及每个角色包含的所有权限组的信息,以及每个权限组所包含的权限的内容;
(2)根据一个权限组找到所有具备此权限组的角色以及每个角色所拥有的管理员信息;
角色_权限组
表是关系表,保存的是两个外键的关联关系,不需要为其生成映射类。只有实体表才需要生成映射类,多对多的中间转换表只需通过类属性的关系引用即可。
class Admin {
private String aid;
private String password;
private Role role;
public void setRole(Role role) {
this.role = role;
}
public Role getRole() {
return this.role;
}
public Admin(String aid, String password) {
this.aid = aid;
this.password = password;
}
public String getInfo() {
return "管理员编号:" + this.aid + ",管理员密码:" + this.password;
}
}
class Role {
private int rid;
private String title;
private Admin admins[];
private Group groups[];
public void setAdmins(Admin admins[]) {
this.admins = admins;
}
public Admin[] getAdmins() {
return this.admins;
}
public void setGroups(Group groups[]) {
this.groups = groups;
}
public Group[] getGroups() {
return this.groups;
}
public Role(int rid, String title) {
this.rid = rid;
this.title = title;
}
public String getInfo() {
return "角色编号:" + this.rid + ",角色名称" + this.title;
}
}
class Group {
private int gid;
private String title;
private Role roles[];
private Action actions[];
public void setActions(Action actions[]) {
this.actions = actions;
}
public Action[] getActions() {
return this.actions;
}
public void setRoles(Role roles[]) {
this.roles = roles;
}
public Role[] getRoles() {
return this.roles;
}
public Group(int gid, String title) {
this.gid = gid;
this.title = title;
}
public String getInfo() {
return "权限组编号:" + this.gid + ",权限组名称:" + this.title;
}
}
class Action {
private int aid;
private String title;
private String url;
private Group group;
public void setGroup(Group group) {
this.group = group;
}
public Group getGroup() {
return this.group;
}
public Action(int aid, String title, String url) {
this.aid = aid;
this.title = title;
this.url = url;
}
public String getInfo() {
return "权限编号:" + this.aid + "权限名称:" + this.title + ",权限路径:" + this.url;
}
}
public class Demo {
public static void main(String[] args) {
Admin a1 = new Admin("admin", "123456");
Admin a2 = new Admin("root", "654321");
Admin a3 = new Admin("guest", "654321");
Role r1 = new Role(1, "系统管理员");
Role r2 = new Role(1, "信息管理员");
Group g1 = new Group(10, "信息管理");
Group g2 = new Group(11, "用户管理");
Group g3 = new Group(12, "数据管理");
Group g4 = new Group(13, "接口管理");
Group g5 = new Group(14, "备份管理");
Action ac1 = new Action(1001, "新闻发布", "-");
Action ac2 = new Action(1002, "新闻列表", "-");
Action ac3 = new Action(1003, "新闻审核", "-");
Action ac4 = new Action(1004, "增加用户", "-");
Action ac5 = new Action(1005, "用户列表", "-");
Action ac6 = new Action(1006, "登陆日志", "-");
Action ac7 = new Action(1007, "雇员数据", "-");
Action ac8 = new Action(1008, "部门数据", "-");
Action ac9 = new Action(1009, "公司数据", "-");
Action ac10 = new Action(1010, "服务传输", "-");
Action ac11 = new Action(1011, "短信平台", "-");
Action ac12 = new Action(1012, "全部备份", "-");
Action ac13 = new Action(1013, "局部备份", "-");
a1.setRole(r1);
a2.setRole(r2);
a3.setRole(r2);
r1.setAdmins(new Admin[]{a1});
r2.setAdmins(new Admin[]{a2, a3});
r1.setGroups(new Group[]{g1, g2, g3, g4, g5});
r2.setGroups(new Group[]{g1, g2});
g1.setRoles(new Role[]{r1, r2});
g2.setRoles(new Role[]{r1, r2});
g3.setRoles(new Role[]{r1});
g4.setRoles(new Role[]{r1});
g5.setRoles(new Role[]{r1});
g1.setActions(new Action[]{ac1, ac2, ac3});
g2.setActions(new Action[]{ac4, ac5, ac6});
g3.setActions(new Action[]{ac7, ac8, ac9});
g4.setActions(new Action[]{ac10, ac11});
g5.setActions(new Action[]{ac12, ac13});
ac1.setGroup(g1);
ac2.setGroup(g1);
ac3.setGroup(g1);
ac4.setGroup(g2);
ac5.setGroup(g2);
ac6.setGroup(g2);
ac7.setGroup(g3);
ac8.setGroup(g3);
ac9.setGroup(g3);
ac10.setGroup(g4);
ac11.setGroup(g4);
ac12.setGroup(g5);
ac13.setGroup(g5);
System.out.println(a1.getInfo());
System.out.println(a1.getRole().getInfo());
for (int x = 0; x < a1.getRole().getGroups().length; x++) {
System.out.println("\t|-" + a1.getRole().getGroups()[x].getInfo());
for (int y = 0; y < a1.getRole().getGroups()[x].getActions().length; y++) {
System.out.println("\t\t|-" + a1.getRole().getGroups()[x].getActions()[y].getInfo());
}
}
System.out.println("-------------------------------------------------");
System.out.println(g2.getInfo());
for (int x = 0; x < g2.getRoles().length; x++) {
System.out.println(g2.getRoles()[x].getInfo());
for (int y = 0; y < g2.getRoles()[x].getAdmins().length; y++) {
System.out.println("\t\t|-" + g2.getRoles()[x].getAdmins()[y].getInfo());
}
System.out.println();
}
}
}
This blog is under a CC BY-NC-SA 3.0 Unported License
本文链接:http://yov.oschina.io/article/Java/Java Base/Java基础知识(七)/